home *** CD-ROM | disk | FTP | other *** search
/ United Public Domain Gold 2 / United Public Domain Gold 2.iso / utilities / pu660.dms / pu660.adf / Vmem / vmemsupp.a < prev   
Text File  |  1991-12-19  |  18KB  |  652 lines

  1. **
  2. ** VMEM - a virtual memory manager for the Amiga operating system
  3. **
  4. ** Version 0.1 ©1990 by Edward Hutchins
  5. ** Based in part on the SetCPU program by Dave Haynie
  6. ** Authors:
  7. **
  8. **    Edward Hutchins: eah1@cec1.wustl.edu
  9. **    Loren Rittle: l-rittle@uiuc.edu
  10. **
  11. ** Revisions:
  12. ** 12/19/91 code released as freeware under the GNU general public license - Ed.
  13. **
  14. **    This program is free software; you can redistribute it and/or modify
  15. **    it under the terms of the GNU General Public License as published by
  16. **    the Free Software Foundation; either version 1, or (at your option)
  17. **    any later version.
  18. **
  19. **    This program is distributed in the hope that it will be useful,
  20. **    but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. **    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  22. **    GNU General Public License for more details.
  23. **
  24. **    You should have received a copy of the GNU General Public License
  25. **    along with this program; if not, write to the Free Software
  26. **    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  27. **
  28.  
  29.     CSECT code
  30.  
  31. **
  32. ** Global variables from VMEM.C
  33. **
  34.  
  35.     XREF    _PhysicalPages        ;    UWORD
  36.     XREF    _VirtualPages        ;    UWORD
  37.     XREF    _ROMBase            ;    APTR
  38.     XREF    _PhysBase            ;    APTR
  39.     XREF    _PageTable            ;    PD_SHORT * (ULONG)
  40.     XREF    _PhysPageDesc        ;    PHYS_DESC * (UBYTE)
  41.     XREF    _SysBusErrHandler    ;    *()
  42.     XREF    _PageDaemonTask        ;    struct Task *
  43.     XREF    _PageDaemonSig        ;    ULONG
  44.     XREF    _FastMemHeader        ;    struct MemHeader *
  45.     XREF    _PageFaultList        ;    struct MinList
  46.     XREF    _PendingPageFaults    ;    UWORD
  47.     
  48. **
  49. ** Exported functions in this module
  50. **
  51.  
  52.     XDEF    _GetCPUType            ;    ID the CPU
  53.     XDEF    _GetCACR            ;    Get 020/030 CACR register
  54.     XDEF    _SetCACR            ;    Set 020/030 CACR register
  55.     XDEF    _GetMMUType            ;    Returns the type of MMU
  56.     XDEF    _GetCRP                ;    Gets MMU CRP register
  57.     XDEF    _SetCRP                ;    Sets MMU CRP register
  58.     XDEF    _GetTC                ;    Gets MMU TC register
  59.     XDEF    _SetTC                ;    Gets MMU TC register    
  60.     XDEF    _GetFPUType            ;    Gets the FPU type    
  61.     XDEF    _InsertFaultHandler    ;    sets up the fault handler
  62.     XDEF    _HandlePageFault    ;    make visible to the debugger
  63.     XDEF    _RestartTask        ;    make visible to the debugger
  64.  
  65. **
  66. **    External functions
  67. **
  68.  
  69.     XREF    _AbsExecBase
  70.     XREF    _LVOFindTask
  71.     XREF    _LVOAllocTrap
  72.     XREF    _LVOFreeTrap
  73.     XREF    _LVOAllocate
  74.     XREF    _LVODeallocate
  75.     XREF    _LVOAllocSignal
  76.     XREF    _LVOFreeSignal
  77.     XREF    _LVOSignal
  78.     XREF    _LVOWait
  79.     XREF    _LVOSupervisor
  80.     XREF    _LVOForbid
  81.     XREF    _LVOPermit
  82.     XREF    _LVODisable
  83.     XREF    _LVOEnable
  84.  
  85. **
  86. **    Macros & constants used herein...
  87. **
  88.  
  89. CALLSYS    macro    *
  90.         jsr        _LVO\1(A6)
  91.         endm
  92.  
  93. CIB_ENABLE        equ    0
  94. CIB_FREEZE        equ    1
  95. CIB_ENTRY        equ    2
  96. CIB_CLEAR        equ    3
  97. CIB_BURST        equ    4
  98.  
  99. CDB_ENABLE        equ    8
  100. CDB_FREEZE        equ    9
  101. CDB_ENTRY        equ    10
  102. CDB_CLEAR        equ    11
  103. CDB_BURST        equ    12
  104. CDB_WALLOC        equ    13
  105.  
  106. AFB_68030        equ    2
  107.  
  108. ATNFLGS            equ    $129
  109.  
  110. ** mask off the vector information
  111. SS_VECTOR        equ    $6
  112. SS_FORMAT_MASK    equ    $F000
  113.  
  114. ** short bus cycle fault stack frame (16 words)
  115. SSF_SIZE        equ    $20
  116. SSF_LSIZE        equ    $08        ; size in longwords
  117. SSF_FORMAT        equ    $A000
  118.  
  119. SSF_SR            equ    $0
  120. SSF_PC            equ    $2
  121. SSF_VECTOR        equ    $6
  122. SSF_SSR            equ    $A
  123. SSF_PIPE_C        equ    $C
  124. SSF_PIPE_B        equ    $E
  125. SSF_DATA_ADDR    equ    $10
  126. SSF_DOB            equ    $18
  127.  
  128. ** long bus cycle fault stack frame (46 words)
  129. LSF_SIZE        equ    $5C
  130. LSF_LSIZE        equ    $17        ; size in longwords
  131. LSF_FORMAT        equ    $B000
  132.  
  133. LSF_SR            equ    $0
  134. LSF_PC            equ    $2
  135. LSF_VECTOR        equ    $6
  136. LSF_SSR            equ    $A
  137. LSF_PIPE_C        equ    $C
  138. LSF_PIPE_B        equ    $E
  139. LSF_DATA_ADDR    equ    $10
  140. LSF_DOB            equ    $18
  141. LSF_STAGEB_ADDR    equ    $24
  142. LSF_DIB            equ    $2C
  143.  
  144. ** special status bits
  145. SSTAT_FC        equ    $8000    ; fault on stage C of the instruction pipe
  146. SSTAT_FB        equ    $4000    ; fault on stage B
  147. SSTAT_RC        equ    $2000    ; stage C re-run
  148. SSTAT_RB        equ    $1000    ; stage B re-run
  149. SSTAT_DF        equ    $0100    ; data fault
  150. SSTAT_RM        equ    $0080    ; read-modify-write cycle
  151. SSTAT_RW        equ    $0040    ; read/write indicator
  152. SSTAT_SIZE_MASK    equ    $0030    ; size of data transfer
  153.  
  154. ** the size of a fault node - 1K
  155. FAULTNODE_SIZE    equ    $400
  156. FAULT_FRAME        equ    80        ; Frame in FaultNode -> 8 + 15*4 + 4 + 4 + 4
  157.  
  158. **
  159. **    Need just a little more stuff
  160. **
  161.  
  162.     NOLIST
  163.     include "exec/execbase.i"
  164.     include "exec/tasks.i"
  165.     include    "exec/lists.i"
  166.     LIST
  167.  
  168. ***********************************************************************
  169. **
  170. **    This section contains functions that identify and operate on CPU 
  171. **    things.
  172. **
  173. ***********************************************************************
  174.  
  175. ;======================================================================
  176. ;
  177. ;    This function returns the type of the CPU in the system as a
  178. ;    longword: 68000, 68010, 68020, or 68030.  The testing must be done
  179. ;    in reverse order, in that any higher CPU also has the bits set for
  180. ;    a lower CPU.  Also, since 1.3 doesn't recognize the 68030, if I
  181. ;    find the 68020 bit set, I always check for the presence of a 
  182. ;    68030.
  183. ;
  184. ;    This routine should be the first test routine called under 1.2
  185. ;    and 1.3.
  186. ;
  187. ;    ULONG GetCPUType();
  188. ;
  189. ;======================================================================
  190.  
  191. _GetCPUType:
  192.     movem.l    a4/a5,-(sp)        ; Save this register
  193.     move.l    _AbsExecBase,a6        ; Get ExecBase
  194.     btst.b    #AFB_68030,ATNFLGS(a6)    ; Does the OS think an '030 is here?
  195.     beq.s    0$
  196.     move.l    #68030,d0        ; Sure does...
  197.     movem.l    (sp)+,a4/a5
  198.     rts
  199.  
  200. 0$    btst.b    #AFB_68020,ATNFLGS(a6)    ; Maybe a 68020
  201.     bne.s    2$
  202.     btst.b    #AFB_68010,ATNFLGS(a6)    ; Maybe a 68010?
  203.     bne.s    1$
  204.     move.l    #68000,d0        ; Just a measley '000
  205.     movem.l    (sp)+,a4/a5
  206.     rts
  207.  
  208. 1$    move.l    #68010,d0        ; Yup, we're an '010
  209.     movem.l    (sp)+,a4/a5
  210.     rts
  211.  
  212. 2$    move.l    #68020,d0        ; Assume we're an '020
  213.     lea    3$,a5            ; Get the start of the supervisor code
  214.     CALLSYS    Supervisor
  215.     movem.l    (sp)+,a4/a5
  216.     rts
  217.  
  218. 3$    movec    cacr,d1            ; Get the cache register
  219.     move.l    d1,a4            ; Save it for a minute
  220.     bset.l    #CIB_BURST,d1        ; Set the inst burst bit
  221.     bclr.l    #CIB_ENABLE,d1        ; Clear the inst cache bit
  222.     movec    d1,cacr            ; Try to set the CACR
  223.     movec    cacr,d1
  224.     btst.l    #CIB_BURST,d1        ; Do we have a set burst bit?
  225.     beq.s    4$
  226.     move.l    #68030,d0        ; It's a 68030
  227.     bset.b    #AFB_68030,ATNFLGS(a6)
  228.  
  229. 4$    move.l    a4,d1            ; Restore the original CACR
  230.     movec    d1,cacr
  231.     rte
  232.  
  233. ;======================================================================
  234. ;
  235. ;    This function returns the 68020/68030 CACR register.  It assumes
  236. ;    a 68020 or 68030 based system.
  237. ;
  238. ;    ULONG GetCACR()
  239. ;
  240. ;======================================================================
  241.  
  242. _GetCACR:
  243.     move.l    _AbsExecBase,a6        ; Get ExecBase
  244.     btst.b    #AFB_68020,ATNFLGS(a6)    ; Does the OS think an '020 is here?
  245.     bne.s    1$
  246.     moveq    #0,d0            ; No CACR here, pal
  247.     rts
  248.  
  249. 1$    move.l    a5,-(sp)        ; Save this register
  250.     lea    2$,a5            ; Get the start of the supervisor code
  251.     CALLSYS    Supervisor
  252.     move.l    (sp)+,a5        ; Give back registers
  253.     rts
  254.  
  255. 2$    movec    cacr,d0            ; Make CACR the return value
  256.     rte
  257.  
  258. ;======================================================================
  259. ;
  260. ;    This function sets the value of the 68020/68030 CACR register.  
  261. ;    It assumes a 68020 or 68030 based system.
  262. ;
  263. ;    void SetCACR(cacr)
  264. ;    ULONG cacr;
  265. ;
  266. ;======================================================================
  267.  
  268. _SetCACR:
  269.     move.l    4(sp),d0        ; New CACR is on stack
  270.     move.l    _AbsExecBase,a6        ; Get ExecBase
  271.     btst.b    #AFB_68020,ATNFLGS(a6)    ; Does the OS think an '020 is here?
  272.     bne.s    1$
  273.     rts                ; No CACR here, pal
  274.  
  275. 1$    move.l    a5,-(sp)        ; Save this register
  276.     lea    2$,a5            ; Get the start of the supervisor code
  277.     CALLSYS    Supervisor
  278.     move.l    (sp)+,a5        ; Give back register
  279.     rts
  280.  
  281. 2$    movec    d0,cacr            ; Set the CACR
  282.     rte
  283.  
  284. ***********************************************************************
  285. **
  286. **    Functions that identify and operate on MMU things.
  287. **
  288. ***********************************************************************
  289.  
  290. ;======================================================================
  291. ;
  292. ;    This function returns 0L if the system contains no MMU, 
  293. ;    68851L if the system does contain an 68851, or 68030L if the
  294. ;    system contains a 68030.
  295. ;
  296. ;    This routine seems to lock up on at least some CSA 68020 
  297. ;    boards, though it runs just fine on those from Ronin and 
  298. ;    Commodore, as well as all 68030 boards it's been tested on.
  299. ;
  300. ;    ULONG GetMMUType()
  301. ;
  302. ;======================================================================
  303.  
  304. _GetMMUType:
  305.     move.l    _AbsExecBase,a6        ; Get ExecBase
  306.     movem.l    a3/a4/a5,-(sp)        ; Save this stuff
  307.     moveq    #0,d0
  308.     move.l    d0,a1
  309.     CALLSYS    FindTask        ; Call FindTask(0L)
  310.     move.l    d0,a3
  311.  
  312.     move.l    TC_TRAPCODE(a3),a4    ; Change the exception vector
  313.     move.l    #2$,TC_TRAPCODE(a3)
  314.     
  315.     subq.l    #4,sp            ; Let's try an MMU instruction
  316.     pmove    tc,(sp)
  317.     cmpi    #0,d0            ; Any MMU here?
  318.     beq.s    1$
  319.     btst.b    #AFB_68030,ATNFLGS(a6)    ; Does the OS think an '030 is here?
  320.     beq.s    1$
  321.     move.l    #68030,d0
  322.  
  323. 1$    addq.l    #4,sp            ; Return that local
  324.     move.l    a4,TC_TRAPCODE(a3)    ; Reset exception stuff
  325.     movem.l    (sp)+,a3/a4/a5        ; and return the registers
  326.     rts
  327.  
  328.     ; This is the exception code.  No matter what machine we're on,
  329.     ; we get an exception.  If the MMU's in place, we should get a
  330.     ; privilige violation; if not, an F-Line emulation exception.
  331.  
  332. 2$    move.l    (sp)+,d0        ; Get Amiga supplied exception #
  333.     cmpi    #11,d0            ; Is it an F-Line?
  334.     beq.s    3$            ; If so, go to the fail routine
  335.     move.l    #68851,d0        ; We have MMU
  336.     addq.l    #4,2(sp)        ; Skip the MMU instruction
  337.     rte
  338.  
  339. 3$    moveq.l    #0,d0            ; It dinna woik,
  340.     addq.l    #4,2(sp)        ; Skip the MMU instruction
  341.     rte
  342.  
  343. ;======================================================================
  344. ;
  345. ;    This function returns the MMU CRP register.  It assumes a 68020 
  346. ;    system with MMU, or a 68030 based system (eg, test for MMU before
  347. ;    you call this, or you wind up in The Guru Zone).  Note that the
  348. ;    CRP register is two longwords long.
  349. ;
  350. ;    void GetCRP(ULONG *)
  351. ;
  352. ;======================================================================
  353.  
  354. _GetCRP:
  355.     move.l    4(sp),a0        ; Pointer to the CRP storage area
  356.     move.l    _AbsExecBase,a6        ; Get ExecBase
  357.     move.l    a5,-(sp)
  358.     lea    2$,a5            ; Get the start of the supervisor code
  359.     CALLSYS    Supervisor
  360.     move.l    (sp)+,a5
  361.     rts
  362.  
  363. 2$    pmove    crp,(a0)
  364.     rte
  365.  
  366. ;======================================================================
  367. ;
  368. ;    This function sets the MMU CRP register.  It assumes a 68020 
  369. ;    system with MMU, or a 68030 based system (eg, test for MMU before
  370. ;    you call this, or you wind up in The Guru Zone).  Note that the
  371. ;    CRP register is two longwords long.
  372. ;
  373. ;    void SetCRP(ULONG *)
  374. ;
  375. ;======================================================================
  376.  
  377. _SetCRP:
  378.     move.l    4(sp),a0        ; Pointer to the CRP storage area
  379.     move.l    _AbsExecBase,a6        ; Get ExecBase
  380.     move.l    a5,-(sp)
  381.     lea    2$,a5            ; Get the start of the supervisor code
  382.     CALLSYS    Supervisor
  383.     move.l    (sp)+,a5        ; Give back registers
  384.     rts
  385.  
  386. 2$    pflusha                    ; explicitly flush the ATC for now
  387.     pmove    (a0),crp
  388.     rte
  389.  
  390. ;======================================================================
  391. ;
  392. ;    This function returns the MMU TC register.  It assumes a 68020 
  393. ;    system with MMU, or a 68030 based system (eg, test for MMU before
  394. ;    you call this, or you wind up in The Guru Zone).  
  395. ;
  396. ;    ULONG GetTC()
  397. ;
  398. ;======================================================================
  399.  
  400. _GetTC:
  401.     move.l    _AbsExecBase,a6        ; Get ExecBase
  402.     move.l    a5,-(sp)
  403.     subq.l    #4,sp            ; Make a place to dump TC
  404.     move.l    sp,a0
  405.     lea    2$,a5            ; Get the start of the supervisor code
  406.     CALLSYS    Supervisor
  407.     move.l    (sp),d0            ; Here's the result
  408.     addq.l    #4,sp
  409.     move.l    (sp)+,a5
  410.     rts
  411.  
  412. 2$    pmove    tc,(a0)
  413.     rte
  414.  
  415. ;======================================================================
  416. ;
  417. ;    This function sets the MMU TC register.  It assumes a 68020 
  418. ;    system with MMU, or a 68030 based system (eg, test for MMU before
  419. ;    you call this, or you wind up in The Guru Zone).  
  420. ;
  421. ;    void SetTC(ULONG)
  422. ;
  423. ;======================================================================
  424.  
  425. _SetTC:
  426.     lea    4(sp),a0        ; Get address of our new TC value
  427.     move.l    _AbsExecBase,a6        ; Get ExecBase
  428.     move.l    a5,-(sp)
  429.     lea    2$,a5            ; Get the start of the supervisor code
  430.      CALLSYS    Supervisor
  431.     move.l    (sp)+,a5
  432.     rts
  433.  
  434. 2$    pflusha                ; explicitly flush the ATC for now
  435.     pmove    (a0),tc
  436.     rte
  437.  
  438.  
  439. ***********************************************************************
  440. **
  441. **    This section contains functions that identify and operate on
  442. **    FPU things.  
  443. **
  444. ***********************************************************************
  445.  
  446. ;======================================================================
  447. ;
  448. ;    This function returns the type of the FPU in the system as a
  449. ;    longword: 0 (no FPU), 68881, or 68882.
  450. ;
  451. ;    ULONG GetFPUType();
  452. ;
  453. ;======================================================================
  454.  
  455. _GetFPUType:
  456.     move.l    a5,-(sp)        ; Save this register
  457.     move.l    _AbsExecBase,a6        ; Get ExecBase
  458.     btst.b    #AFB_68881,ATNFLGS(a6)    ; Does the OS think an FPU is here?
  459.     bne.s    1$    
  460.     moveq.l    #0,d0            ; No FPU here, dude
  461.     move.l    (sp)+,a5        ; Give back the register
  462.     rts
  463.  
  464. 1$    lea    2$,a5            ; Get the start of the supervisor code
  465.     CALLSYS    Supervisor
  466.     move.l    (sp)+,a5        ; Give back registers
  467.     rts
  468.  
  469. 2$    move.l    #68881,d0        ; Assume we're a 68881
  470.     fsave    -(sp)            ; Test and check
  471.     moveq.l    #0,d1
  472.     move.b    1(sp),d1        ; Size of this frame
  473.     cmpi    #$18,d1
  474.     beq    3$
  475.     move.l    #68882,d0        ; It's a 68882
  476.  
  477. 3$    frestore (sp)+            ; Restore the stack
  478.     rte
  479.  
  480. ***********************************************************************
  481. **
  482. **    Here come the page fault exception handlers
  483. **
  484. ***********************************************************************
  485.  
  486. ;======================================================================
  487. ;
  488. ;    InsertFaultHandler - trap the system buserr vector (VBR + $
  489. ;
  490. ;======================================================================
  491.  
  492. _InsertFaultHandler:
  493.     move.l    a5,-(sp)        ; save a5
  494.     move.l    _AbsExecBase,a6        ; get ExecBase
  495.     lea    1$,a5            ; get the start of the supervisor code
  496.     CALLSYS    Supervisor
  497.     move.l    (sp)+,a5        ; restore a5
  498.     rts
  499.  
  500. 1$    movec    VBR,a0            ; get the vector base register
  501.     lea    8(a0),a0        ; BUSERR exception vector
  502.     move.l    (a0),_SysBusErrHandler    ; save the current bus err handler
  503.     move.l    #_HandlePageFault,(a0)    ; install ourself
  504.     rte
  505.  
  506. ;======================================================================
  507. ;
  508. ;    HandlePageFault - determine whether a bus error was caused by
  509. ;    a page fault, and handle it if it was.
  510. ;    (for now, assume this is a page fault)
  511. ;
  512. ;======================================================================
  513.  
  514. _HandlePageFault:
  515.     movem.l    d0-d7/a0-a6,-(sp)    ; save registers on system stack
  516.     move.l    _AbsExecBase,a6        ; Get ExecBase
  517.     CALLSYS    Disable                ; just to be sure
  518.     move.l    _FastMemHeader,a0    ; allocate a fault node
  519.     move.l    #FAULTNODE_SIZE,d0
  520.     CALLSYS    Allocate
  521.     tst.l    d0                    ; did it work?
  522.     bne.s    1$
  523.  
  524.     movem.l    (sp)+,d0-d7/a0-a6    ; allocation failed, GURU time!
  525. 4$    move.l    a0,-(sp)            ; save a spot on the stack
  526.     move.l    a0,-(sp)            ; save the register
  527.     move.l    _SysBusErrHandler,a0    ; normal bus error
  528.     move.l    a0,4(sp)            ; set the return address
  529.     move.l    (sp)+,a0            ; restore register
  530.     rts                            ; jump to the big guru error
  531.  
  532. 1$    move.l    d0,a5                ; point at the memory block
  533.     add.l    #FAULTNODE_SIZE,d0    ; point to the end of the node
  534.     move.l    d0,a4                ; a4 is the fake user stack pointer
  535.  
  536.     lea        _PageFaultList,a0    ; where the faults are queued up
  537.     move.l    a5,a1                ; this node
  538.     ADDTAIL                        ; add this FaultNode to the tail of the queue
  539.     addq.w    #1,_PendingPageFaults    ; count number of faults
  540.  
  541.     lea        8(a5),a3            ; save the registers in the fault node
  542.     moveq    #14,d0                ; number of registers - 1
  543. 2$    move.l    (sp)+,(a3)+            ; copy a longword
  544.     dbra    d0,2$                ; do it 15 times
  545.  
  546.     move    usp,a0                ; get the real user stack pointer
  547.     move.l    a0,(a3)+            ; save it
  548.  
  549.     move.l    #_RestartTask,-(a4)    ; put the fake return address on the stack
  550.     move    a4,usp                ; fake in the user stack pointer
  551.  
  552.     moveq    #0,d0
  553.     move.l    d0,a1                ; NULL task name
  554.     CALLSYS    FindTask            ; find ourselves
  555.     move.l    d0,(a3)+            ; save it
  556.  
  557.     moveq    #-1,d7                ; don't care which signal
  558.     move.l    d7,d0
  559.     CALLSYS    AllocSignal            ; this is the wake up signal
  560.     cmp.l    d0,d7                ; did we get one?
  561.     beq.s    4$                    ; nope, GURU time!
  562.     move.l    d0,d7                ; save this for later
  563.     move.b    d0,(a3)+            ; save the signal number
  564.     addq.l    #3,a3                ; padding
  565.  
  566.     move.w    SS_VECTOR(sp),d0    ; get the frame vector and type
  567.     andi.w    #SS_FORMAT_MASK,d0    ; mask off the format bits
  568.  
  569.     cmpi.w    #SSF_FORMAT,d0        ; short?
  570.     bne.s    3$
  571.     moveq    #SSF_LSIZE-1,d0        ; size in longwords - 1
  572.     bra.s    5$
  573.  
  574. 3$    cmpi.w    #LSF_FORMAT,d0        ; long?
  575.     bne        4$                    ; GURU time again... (not a short branch)
  576.     moveq    #LSF_LSIZE-1,d0        ; size in longwords - 1
  577.  
  578. 5$    move.l    (sp)+,(a3)+            ; copy the fault stack frame
  579.     dbra    d0,5$
  580.  
  581.     move.w    #0,-(sp)            ; create a fake exception frame
  582.     lea        _LVOSignal(a6),a0    ; where to return to
  583.     move.l    a0,-(sp)            ; push it
  584.     move    sr,d0                ; get the status register
  585.     andi.w    #$DFFF,d0            ; clear the supervisor bit
  586.     move.w    d0,-(sp)            ; push the new status
  587.  
  588.     move.l    _PageDaemonTask,a1    ; the daemon to wake
  589.     move.l    _PageDaemonSig,d0    ; signal to wake the daemon
  590.     rte                            ; do it!
  591.  
  592. ;======================================================================
  593. ;
  594. ;    RestartTask - restore the state information in the fault node,
  595. ;    free the fault node, and restart the faulted task.
  596. ;
  597. ;    on entry, a6 -> ExecBase, a5 -> FaultNode, d7 = WakeSigNum
  598. ;
  599. ;======================================================================
  600.  
  601. _RestartTask:
  602.     moveq.l    #1,d0
  603.     lsl.l    d7,d0                ; signal to wait for
  604.     CALLSYS    Wait                ; wait till we're paged in
  605.  
  606.     move.l    d7,d0                ; we no longer need the signal
  607.     CALLSYS    FreeSignal
  608.  
  609.     move.l    a5,a4                ; Supervisor clobbers a5
  610.     lea        1$,a5                ; where to continue...
  611.     CALLSYS    Supervisor            ; drop into supervisor mode
  612.  
  613. 1$    addq    #8,sp                ; pop the fake frame from the sys stack
  614.     move.l    a4,a5                ; a5 -> FaultNode again
  615.  
  616.     lea        FAULT_FRAME(a5),a4    ; point at the fault frame
  617.  
  618.     move.w    SS_VECTOR(a4),d0    ; get the frame vector and type
  619.     andi.w    #SS_FORMAT_MASK,d0    ; mask off the format bits
  620.  
  621.     cmpi.w    #SSF_FORMAT,d0        ; short?
  622.     bne.s    2$
  623.     moveq    #SSF_LSIZE-1,d0        ; size in longwords - 1
  624.     lea        SSF_SIZE(a4),a4        ; point at the end
  625.     bra.s    3$
  626.  
  627. 2$    moveq    #LSF_LSIZE-1,d0        ; assume long (size in longwords - 1)
  628.     lea        LSF_SIZE(a4),a4        ; point at the end
  629.  
  630. 3$    move.l    -(a4),-(sp)            ; copy the fault stack frame back
  631.     dbra    d0,3$
  632.  
  633.     subq.l    #8,a4                ; skip SigNum and Task *
  634.     move.l    -(a4),a0            ; real user stack pointer
  635.     move    a0,usp                ; fix the user stack
  636.  
  637.     moveq    #14,d0                ; number of registers - 1
  638. 4$    move.l    -(a4),-(sp)            ; copy the saved registers (FPx are ok)
  639.     dbra    d0,4$
  640.  
  641.     move.l    _FastMemHeader,a0    ; free the fault node (we're unlinked)
  642.     move.l    a5,a1                ; the node address
  643.     move.l    #FAULTNODE_SIZE,d0    ; how big it is
  644.     CALLSYS    Deallocate
  645.  
  646.     pflusha                        ; flush all ATC registers for now...
  647.     CALLSYS    Enable                ; turn multitasking back on
  648.     movem.l    (sp)+,d0-d7/a0-a6    ; restore the registers
  649.     rte                            ; and we're off!
  650.  
  651.     end
  652.